package com.znfeiche.server.DAO;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.znfeiche.exception.XMLCRUDException;
import com.znfeiche.server.DO.BaseDO;
/**
 * 此类为一个基础类，提供基础的增删改查功能，
 * 使用时，必须先初始化，即传入文件名称和节点名称，
 * 注：文件名称需包括路径
 * 注：id即为主键，目前不提供修改主键，如果在xml中定义的id重复，则会操作多个
 * 所以最后id为唯一
 * @author 彭琦
 *
 */
public  class BaseDAO {
	private String tableName;
	private String fileName;
	/**
	 * 在其中设置文件名和节点名称
	 */
	public  void init(String fileName,String tableName){
		this.fileName = fileName;
		this.tableName = tableName;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public String getTableName() {
		return tableName;
	}
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}
	/**
	 * 插入数据 
	 * @param baseDO
	 * @throws XMLCRUDException 
	 */
	public int insertSelective(BaseDO baseDO) throws XMLCRUDException{
		SAXReader reader = new SAXReader();
		Document doc = null;
		int count = 0;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			Element e = null;
			//如果节点为空（第一次插入）
			if(eles==null||eles.size()<1){
				e = root.addElement(tableName);
				eles   = root.elements(tableName);
			}
			//如果存在（id相同），则提示
			for(Element ele :eles){
				String id = ele.attributeValue("id");
				if(id!=null){
					if(id.equals(baseDO.getId())){
						throw new XMLCRUDException("该记录已存在！");
					}
				}
			}
			if(e==null){
				e = root.addElement(tableName);
			}
			if(baseDO.getId()!=null){
				e.addAttribute("id", baseDO.getId());
			}
			//如果不存在，则新增
			Map<Method,String> getMethod = getGetMethods(baseDO);
			Set<Method> methods = getMethod.keySet();
			for(Method method:methods){
				String fieldName = getMethod.get(method);
				if(!(method.invoke(baseDO) instanceof String)){
					insertSelective((BaseDO)method.invoke(baseDO));
				}else{
					String value = (String) method.invoke(baseDO);
					if(value!=null&&!"".equals(value)){//如果有值，则修改
						Element el = null;
						try{
							el = e.element(fieldName);
							if(el==null){
								el = e.addElement(fieldName);
							}
						}catch(Exception e1){
							el = e.addElement(fieldName);
						}
						el.setText(value);
					}else{//如果无值，则删除
						try {
							Element el = e.element(fieldName);
							el.detach();
						} catch (Exception e1) {
							System.out.println("节点【"+fieldName+"】不存在，无需删除！");
						}
						
					}
				}
				
				
			}
			count++;
			 //指定文件输出的位置
	        FileOutputStream out =new FileOutputStream(fileName);
	        
	        // 指定文本的写出的格式：
	        OutputFormat format=OutputFormat.createPrettyPrint();   //漂亮格式：有空格换行
	        format.setEncoding("UTF-8");
	        
	        //1.创建写出对象
	        XMLWriter writer=new XMLWriter(out,format);
	           
	        //2.写出Document对象
	        writer.write(doc);
	        
	        //3.关闭流
	        writer.close();
			
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return count;
	}
	/**
	 * 根据id修改数据  如果传入的数据为空，则修改为空
	 * @param baseDO
	 * @return 修改的数目
	 */
	public int update(BaseDO baseDO){
		SAXReader reader = new SAXReader();
		Document doc = null;
		int count = 0;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			for(Element ele :eles){
				String id = ele.attributeValue("id");
				if(id.equals(baseDO.getId())){
					Map<Method,String> getMethod = getGetMethods(baseDO);
					Set<Method> methods = getMethod.keySet();
					for(Method method:methods){
						String fieldName = getMethod.get(method);
						String value = (String) method.invoke(baseDO);
						if(value!=null&&!"".equals(value)){//如果有值，则修改
							Element el = null;
							try{
								el = ele.element(fieldName);
							}catch(Exception e){
								el = ele.addElement(fieldName);
							}
							el.setText(value);
						}else{//如果无值，则删除
							try {
								Element el = ele.element(fieldName);
								el.detach();
							} catch (Exception e) {
								System.out.println("节点【"+fieldName+"】不存在，无需删除！");
							}
							
						}
						
					}
					count++;
				}
			}
			 //指定文件输出的位置
	        FileOutputStream out =new FileOutputStream(fileName);
	        
	        // 指定文本的写出的格式：
	        OutputFormat format=OutputFormat.createPrettyPrint();   //漂亮格式：有空格换行
	        format.setEncoding("UTF-8");
	        
	        //1.创建写出对象
	        XMLWriter writer=new XMLWriter(out,format);
	           
	        //2.写出Document对象
	        writer.write(doc);
	        
	        //3.关闭流
	        writer.close();
			
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return count;
	}
	/**
	 * 根据id修改数据  如果传入的数据为空，则不修改
	 * @param baseDO
	 * @return 修改的数目
	 */
	public int updateSelective(BaseDO baseDO){
		SAXReader reader = new SAXReader();
		Document doc = null;
		int count = 0;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			for(Element ele :eles){
				String id = ele.attributeValue("id");
				if(id.equals(baseDO.getId())){
					Map<Method,String> getMethod = getGetMethods(baseDO);
					Set<Method> methods = getMethod.keySet();
					for(Method method:methods){
						String fieldName = getMethod.get(method);
						String value = (String) method.invoke(baseDO);
						if(value!=null&&!"".equals(value)){
							Element el = null;
							try{
								el = ele.element(fieldName);
							}catch(Exception e){
								el = ele.addElement(fieldName);//如果节点不存在，则新建
							}
							el.setText(value);
						}
						
					}
					count++;
				}
			}
			 //指定文件输出的位置
	        FileOutputStream out =new FileOutputStream(fileName);
	        
	        // 指定文本的写出的格式：
	        OutputFormat format=OutputFormat.createPrettyPrint();   //漂亮格式：有空格换行
	        format.setEncoding("UTF-8");
	        
	        //1.创建写出对象
	        XMLWriter writer=new XMLWriter(out,format);
	           
	        //2.写出Document对象
	        writer.write(doc);
	        
	        //3.关闭流
	        writer.close();
			
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return count;
	}
	public void delete(BaseDO baseDO){
		SAXReader reader = new SAXReader();
		Document doc = null;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			for(Element ele :eles){
				String id = ele.attributeValue("id");
				if(id.equals(baseDO.getId())){
					ele.detach();
				}
			}
			 //指定文件输出的位置
	        FileOutputStream out =new FileOutputStream(fileName);
	        
	        // 指定文本的写出的格式：
	        OutputFormat format=OutputFormat.createPrettyPrint();   //漂亮格式：有空格换行
	        format.setEncoding("UTF-8");
	        
	        //1.创建写出对象
	        XMLWriter writer=new XMLWriter(out,format);
	           
	        //2.写出Document对象
	        writer.write(doc);
	        
	        //3.关闭流
	        writer.close();
			
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	/**
	 * 根据主键查询记录
	 * @param baseDO
	 * @return
	 */
	public BaseDO selectByPrimaryKey(String primaryKey,Class cls){
		SAXReader reader = new SAXReader();
		Document doc = null;
		BaseDO baseDO = null;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			for(Element ele :eles){
				
				String id = ele.attributeValue("id");
				if(primaryKey.equals(id)){
					try {
						baseDO = (BaseDO) cls.newInstance();
					} catch (InstantiationException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					Map<Method,String> setMethod = getSetMethods(baseDO);
					Set<Method> methods = setMethod.keySet();
					for(Method method:methods){
						String fieldName = setMethod.get(method);
						String par = null;
						try{
							par = ele.element(fieldName).getTextTrim();
						}catch(Exception e){//保证程序的健壮性
							System.out.println("节点【"+fieldName+"】不存在!");
							
						}
						
						if( par!=null&& !"".equals(par)){
							method.invoke(baseDO,par);
						}
					}
					baseDO.setId(id);
				}
			}
			
			
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
		return baseDO;
	}
	/**
	 * 根据字段查询记录
	 * @param baseDO
	 * @return
	 */
	public List<BaseDO> selectByDO(String field,Object obj,Class cls){
		List<BaseDO> baseDOs = new ArrayList<BaseDO>();
		SAXReader reader = new SAXReader();
		Document doc = null;
		BaseDO baseDO = null;
		try {
			doc = reader.read(new File(fileName));
			Element root = doc.getRootElement();
			List<Element> eles   = root.elements(tableName);
			for(Element ele :eles){
				String value = null;
				if("id".equals(field)){
					value = ele.attributeValue("id");
				}else{
					try{
						value = ele.element(field).getTextTrim();
					}catch(Exception e){//保证程序的健壮性
						System.out.println("节点【"+field+"】不存在!");
						continue;
					}
				}
				String id = ele.attributeValue("id");
				if(value.equals(obj)){
					try {
						baseDO = (BaseDO) cls.newInstance();
					} catch (InstantiationException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					Map<Method,String> setMethod = getSetMethods(baseDO);
					Set<Method> methods = setMethod.keySet();
					for(Method method:methods){
						String fieldName = setMethod.get(method);
						String par = null;
						try{
							par = ele.element(fieldName).getTextTrim();
						}catch(Exception e){//保证程序的健壮性
							System.out.println("节点【"+fieldName+"】不存在!");
						}
						
						if( par!=null&& !"".equals(par)){
							method.invoke(baseDO,par);
						}
					}
					baseDO.setId(id);
					baseDOs.add(baseDO);
				}
			}
			
			
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
		return baseDOs;
	}
	/**
	 * 获取字段名
	 * @param baseDO
	 * @return
	 */
	private List<String> getGetField(Object baseDO){
		Class cls = baseDO.getClass();
		Field[] fields = cls.getDeclaredFields();
		List<String> fieldNames = new ArrayList<String>();
		for(Field field:fields){
			fieldNames.add(field.getName());
		}
		return fieldNames;
	}
	/**
	 * 获取set方法
	 * @param baseDO
	 * @return
	 */
	private Map<Method,String> getSetMethods(Object baseDO){
		Class cls = baseDO.getClass();
		List<String> fieldNames = getGetField(baseDO);
		Map<Method,String> setMethods = new HashMap<Method,String>();
		try{
			for(String fieldName:fieldNames){
				String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
				Method method = cls.getDeclaredMethod(methodName, String.class);
				System.out.println(method.getName());
				setMethods.put(method,fieldName);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
		return setMethods;
	}
	/**
	 * 获取get方法
	 * @param baseDO
	 * @return
	 */
	private Map<Method,String> getGetMethods(Object baseDO){
		Class cls = baseDO.getClass();
		List<String> fieldNames = getGetField(baseDO);
		Map<Method,String> getMethods = new HashMap<Method,String>();
		try{
			for(String fieldName:fieldNames){
				String methodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
				Method method = cls.getDeclaredMethod(methodName);
				System.out.println(method.getName());
				getMethods.put(method,fieldName);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
		return getMethods;
	}
}
